#pragma once

#include <iostream>
#include <list>
#include <string>

class Component;
class Mediator
{
public:
    virtual void add(Component *component)                    = 0;
    virtual void remove(Component *component)                 = 0;
    virtual void notify(Component *sender, std::string event) = 0;
};

class Component
{
public:
    Component(std::string type, Mediator *mediator = nullptr) : m_type(type), m_mediator(mediator)
    {
    }

public:
    void setMediator(Mediator *mediator)
    {
        this->m_mediator = mediator;
    }

    virtual void       receive(Component *sender) = 0;
    const std::string &type() const
    {
        return m_type;
    }

protected:
    Mediator   *m_mediator;
    std::string m_type;
};

class Seller;
class Buyer : public Component
{
public:
    Buyer(std::string name, int budget) : Component("buyer"), m_name(name), m_budget(budget)
    {
    }

    void receive(Component *seller) override
    {
        std::cout << "去卖家看房." << std::endl;
    }

private:
    std::string m_name;
    int         m_budget;
};

class Seller : public Component
{
public:
    Seller(std::string name, int price) : Component("seller"), m_name(name), m_price(price)
    {
    }

    void receive(Component *buyer) override
    {
        std::cout << "买家来看房." << std::endl;
    }

    void consignment()
    {
        this->m_mediator->notify(this, "consignment");
    }

private:
    std::string m_name;
    int         m_price;
};

class HouseMediator : public Mediator
{
public:
    HouseMediator() = default;

public:
    void add(Component *component) override
    {
        m_components.push_back(component);
    }

    void remove(Component *component) override
    {
        m_components.remove(component);
    }

    void notify(Component *sender, std::string event) override
    {
        if (event == "consignment") {
            for (Component *c : m_components) {
                if (c->type() == "buyer")
                    c->receive(sender);
            }
        } else if (event == "houseView") {
            for (Component *c : m_components) {
                if (c->type() == "seller")
                    c->receive(sender);
            }
        } else if (event == "selled") {
            m_components.remove(sender);
        } else if (event == "buyed") {
            m_components.remove(sender);
        }
    }

private:
    std::list<Component *> m_components;
};
